#include <iostream>
#include <string>
#include <unistd.h>
#include "Socket.hpp"
#include "Protocol.hpp"

using namespace socket_ns;
// clinet ip port
int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        std::cerr << "Usage: " << argv[0] << " serverip serverport" <<std::endl;
    }
    std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);

    SockSPtr sock = std::make_shared<TcpSoket>();
    if (!sock->BuildClientSocket(serverip, serverport))
    {
        // 连接服务端失败
        std::cout << "connect error" << std::endl;
    }

    srand(time(nullptr) ^ getpid());
    std::string opers= "+-*/%&^";
    // 连接成功，开始通信
    while(1)
    {
        //  构建数据
        int x = rand() % 10;
        usleep(x*1000);
        int y = rand() % 10;
        usleep(x*1000);
        char oper = opers[y % opers.size()];

        // 构建请求
        auto req = Factor::BuildRequest();
        req->SetVal(x, y, oper);

        // 1.序列化
        std::string reqstr;
        req->Serialize(&reqstr);

        // 2.添加报头
        reqstr = Encode(reqstr);
        std::cout << "######################" << std::endl;
        std::cout << "reqstr add header:\n" << reqstr << std::endl;

        // 3.发送
        sock->Send(reqstr);

        // 接收数据
        std::string packageStreamQueue;
        while(1)
        {
            // 4.接收应答
            int n = sock->Recv(&packageStreamQueue);
            if (n < 0)
            {
                std::cout << "recv error" << std::endl;
            }

            // 不能保证读取一个完整报文
            // 5.报文解析
            std::string package;
            package = Decode(packageStreamQueue);
            if (package.empty()) continue;
            
            // 6.反序列化
            auto resp = Factor::BuildResponse();
            resp->Deserialize(package);

            // 7.打印
            resp->PrintRet();

            break;
        }

        sleep(1);
    }

    sock->Close();
    return 0;
}